﻿using System;
using System.Collections.Generic;
using System.Collections;
//using System.ComponentModel;
using System.Data;
using System.Drawing;
//using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace LogGrouper
{
    public partial class Form1 : Form
    {
        private Dictionary<string,ArrayList> dic = new Dictionary<string, ArrayList>();
        private string folderToRun;
        private Boolean errorFlag;
        //private string logFolder;
        //private string[] dates;
        //private Boolean multipleTestsToHandleFlag;
        //private DateTime day;
        private Boolean debugFlag;
        //private string curRootFolder;
        private Regex zipReg = new Regex("(zip)$");
        private Regex dateReg = new Regex(@"\[[^]]*]");
        private Regex testReg = new Regex(@"^\d{8}_[^_]+_[^_]+_+[^_]+");
        private Regex folderReg = new Regex(@"\\[^\\]*[\\]?$");
        
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            folderToRun = "";
            //logFolder = "";
            //curRootFolder = "";
            this.errorFlag = false;
            this.debugFlag = false;
            //multipleTestsToHandleFlag = false;
            this.cb_Debug.CheckState = CheckState.Unchecked;
            this.tb_log.Text = "Welcome!\r\nPlease select a folder first.\r\n";
        }

        private void button_folderBrowse_Click(object sender, EventArgs e)
        {
            if (this.folderBrowserDialog1.ShowDialog() == DialogResult.OK) {
                this.folderToRun = folderBrowserDialog1.SelectedPath;
                //logFolder = this.folderToRun + "\\Log\\";
                this.tb_folderDisplay.Text = this.folderToRun;
                this.tb_folderDisplay.Update();
            }
        }

        private void button_run_Click(object sender, EventArgs e)
        {
            int judgeFolderResult = 0;
            judgeFolderResult = judgeFolderType(this.folderToRun);
            //multipleTestsToHandleFlag = false;

            if (judgeFolderResult > 0)
            {
                if (judgeFolderResult > 2)
                {
                    dealwithOneTest(folderToRun);
                }
                else {
                    dealWithMultiTests(this.folderToRun);
                }
            }
            else {
                printTrace("e", "Folder you select is invalid.");
            }

            printTrace("i", "Operation Complete.");

            if (this.errorFlag)
            {
                MessageBox.Show("Error occured. see detailed info from trace.");
            }
        }

        private void printTrace(string type, string trace) {
            string preText = "";
            if (type == "i")
            {
                preText = "[Info]: ";
            }
            else
            {
                if (type == "e")
                {
                    preText = "[Error]: ";
                }
                else {
                    if (type == "w")
                    {
                        preText = "[Warning]: ";
                        this.errorFlag = true;
                    }
                    else {
                        if (!this.debugFlag)
                        {
                            return;
                        }
                        else {
                            preText = "[Debug]: ";
                        }
                    }
                }
            }
            this.tb_log.Text += preText + trace + "\r\n";
            this.tb_log.Update();
        }


        //this function will judge the folder user selected
        //below condition return 1
        //if it's folder type like Drivetest_MUC, set multipleTestsToHandleFlag as true;
        //else set multipleTestsToHandleFlag as false
        //below condition return 0
        //none of the folder type above.
        private int judgeFolderType(string folder) {
            int judgeTestLine;
            judgeTestLine = 0;
            foreach (string tmpFolder in Directory.GetDirectories(folder)) {
                DirectoryInfo di = new DirectoryInfo(tmpFolder);
                if (tmpFolder.Contains("Logs") || tmpFolder.Contains("Result") || tmpFolder.Contains("Data")) {
                    judgeTestLine += 1;
                }
                if (testReg.IsMatch(di.Name )) {
                    //this.multipleTestsToHandleFlag = true;
                    judgeTestLine = 1;
                    break;
                }
            }
            if (judgeTestLine > 2) {
               // this.multipleTestsToHandleFlag = false;
            }

            return judgeTestLine;
        }

        private void dealWithMultiTests(string folder){
            
            foreach (string tmpFolder in Directory.GetDirectories(folder)) {
                //DirectoryInfo tmpDirInfo = new DirectoryInfo(tmpFolder);
                dealwithOneTest(tmpFolder);
            }
        }

        private void dealwithOneTest(string dirPath){
            //this.curRootFolder = dirPath;
            dic.Clear();
            if (this.folderReg.IsMatch(dirPath)) {
                Match mc = folderReg.Match(dirPath);
                printTrace("i", "Parsing foler: " + mc.Value);
            }

            string logPath = dirPath + "\\Logs";
            if (Directory.GetFiles(logPath).Length > 0)
            {
                foreach (string singleFile in Directory.GetFiles(logPath))
                {
                    FileInfo tmpF = new FileInfo(singleFile);
                    string tmpStr = "";
                    if (this.zipReg.IsMatch(singleFile))
                    {
                        if (this.dateReg.IsMatch(tmpF.Name))
                        {
                            MatchCollection mcs = dateReg.Matches(tmpF.Name);
                            tmpStr = mcs[0].Value.Replace("[","");
                            tmpStr = tmpStr.Replace("]", "");
                            if (dic.ContainsKey(tmpStr))
                            {
                                dic[tmpStr].Add(singleFile);
                            }else{
                                ArrayList tmpAL = new ArrayList();
                                tmpAL.Add(singleFile);
                                dic.Add(tmpStr, tmpAL);
                            }
                        }
                    }
                    else
                    {
                        printTrace("w", "Found unzipped file: " + singleFile);
                    }

                }

                    foreach (string key in dic.Keys)
                    {
                        try
                        {
                            if (!Directory.Exists(logPath +"\\"+ key + "_" + getWorkingDay(key))){
                                Directory.CreateDirectory(logPath + "\\"+ key + "_" + getWorkingDay(key));
                            }
                            foreach (string s in dic[key])
                            {
                                FileInfo tmpf = new FileInfo(s);
                                printTrace("i", "move file " + tmpf.Name);
                                File.Move(s, logPath + "\\"+ key + "_" + getWorkingDay(key) + "\\" + tmpf.Name);
                            }
                        } catch (Exception err) {
                            printTrace("e", err.Message);
                            continue;
                        }
                    }

            }
            else
            {
                printTrace("w", "No file found under log folder.");
            }
        }
        //this function will judge one folder and check if files under Log folder need to be deal.
        //if need to be deal, return true
        private Boolean judgeTheTestToDeal(string folder) {
            string thisLogFodler = "";
            if (Directory.Exists(folder + "\\Log\\"))
            {
                thisLogFodler = folder + "\\Log\\";
                if (Directory.GetDirectories(thisLogFodler).Length > 0)
                {
                    return false;
                }
                else {
                    return true;
                }
            }
            else {
                printTrace("d", "Folder no Log Folder.");
                return false;
            }
        }

        private void cb_Debug_CheckedChanged(object sender, EventArgs e)
        {
            this.debugFlag = this.cb_Debug.Checked;
        }

        private string getWorkingDay(string date) {
            string returnStr = "";
            string[] dates = date.Split('-');
            int week = getWeekday(Convert.ToInt32(dates[0]), Convert.ToInt32(dates[1]), Convert.ToInt32(dates[2]));
            switch (week)
            {
                case 1:
                    returnStr = "Monday";
                    break;
                case 2:
                    returnStr = "Tuesday";
                    break;
                case 3:
                    returnStr = "Wednesday";
                    break;
                case 4:
                    returnStr = "Thursday";
                    break;
                case 5:
                    returnStr = "Friday";
                    break;
                case 6:
                    returnStr = "Saturday";
                    break;
                case 7:
                    returnStr = "Sunday";
                    break;
            }
            return returnStr;
        }

        private int getWeekday(int y, int m, int d) {
            if (m == 1) m = 13;
            if (m == 2) m = 14;
            int week = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7 + 1;
            return week;
        }
    }
}
